package org.ccay.manage.security.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.inject.Inject;
import javax.inject.Named;

import org.apache.shiro.authz.AuthorizationInfo;
import org.ccay.core.base.BatchVO;
import org.ccay.core.util.StringUtil;
import org.ccay.manage.security.dao.IPermissionDao;
import org.ccay.manage.security.service.IPermissionManageService;
import org.ccay.security.entity.Permission;
import org.ccay.security.reaml.IPermissionMetadataScanner;
import org.ccay.security.vo.PermissionTreeNodeVO;
import org.ccay.security.vo.ProgramRolesVO;

/**
 *
 * @author chaowangbang
 * @since 2017年2月5日
 */
@Named
public class PermissionManageService implements IPermissionManageService{
	
	@Inject
	IPermissionMetadataScanner scanner;
	
	@Inject
	IPermissionDao permissionDao;

	@Override
	public Set<Permission> findAllPermissionList(){
		return scanner.loadPermissionsMetadatas();
	}
	
	@Override
	public List<PermissionTreeNodeVO> findPermissionTree(Long roleId) {
		//所有权限点
		Set<Permission> allPermissions = scanner.loadPermissionsMetadatas();
		//当前已拥有的权限
		List<String> hasPermissions = new ArrayList<String>();
		if(null != roleId){
			hasPermissions = permissionDao.findPermissionStringByRoleId(roleId);
		}
		//树
		List<PermissionTreeNodeVO> tree = new ArrayList<PermissionTreeNodeVO>();
		for(Permission p : allPermissions){
			if(StringUtil.isNullOrEmpty(p.getResourceName()) || StringUtil.isNullOrEmpty(p.getOperationName())){
				continue;
			}
			String[] rns = p.getResourceName().split("\\|");
			//资源路径中按照|切分的每个元素
			List<PermissionTreeNodeVO> children = tree;
			for(int i=0;i<rns.length;i++){
				String rn = rns[i];
				//通过节点名称查找节点
				PermissionTreeNodeVO cn = findNodeByName(rn,children);
				if(null == cn){
					cn  = new PermissionTreeNodeVO();
					cn.setName(rn);
					children.add(cn);
				}
				if(i == rns.length-1){
					cn.setTitle(p.getResourceDesc());
				}
				children = cn.getChildren();
			}
			//程序到这里拿到的children就是资源下的children 开始添加操作点
			PermissionTreeNodeVO op  = new PermissionTreeNodeVO();
			op.setPermissionName(p.getResourceName()+":"+p.getOperationName());
			op.setPermissionString(p.getPermissionString());
			op.setName(p.getOperationName());
			op.setTitle(p.getOperationDesc());
			//有权限则选中
			if(hasPermissions.contains(p.getPermissionString())){
				op.setChecked(true);
			}
			children.add(op);
		}
		return tree;
	}
	
	@Override
	public void saveRolePermissions(List<String> permissions, Long roleId) {
		permissionDao.deleteRolePermissions(roleId);
		if(!permissions.isEmpty()){
			permissionDao.insertRolePermissions(permissions,roleId);
		}
	}
	
	/**
	 * 通过节点名称查找节点
	 * @param name
	 * @param nodes
	 * @return
	 */
	private PermissionTreeNodeVO findNodeByName(String name,List<PermissionTreeNodeVO> nodes){
		for(PermissionTreeNodeVO node : nodes){
			if(node.getName().equals(name)){
				return node;
			}
		}
		return null;
	}

	@Override
	public List<String> findPermissionStringByRoleId(Long roleId) {
		return permissionDao.findPermissionStringByRoleId(roleId);
	}

	@Override
	public List<ProgramRolesVO> findProgramRolesByUserId(Long roleId) {
		return permissionDao.findProgramRolesByUserId(roleId);
	}

	@Override
	public Map<String, Object> userAuthz(BatchVO<ProgramRolesVO> batchItems, Long userId) {
		Map<String, Object> validateInfo = validateForUserAuthz(batchItems,userId);
		if(validateInfo.isEmpty()){
			permissionDao.userAuthz(batchItems,userId);
		}
		return validateInfo;
	}

	@Override
	public  Map<String, Object> validateForUserAuthz(BatchVO<ProgramRolesVO> batchItems, Long userId) {
		Map<String, Object> errorInfo = new HashMap<String,Object>();
		if(!batchItems.getCreateAndUpdateUnion().isEmpty()){
			//校验提供的新增及修改的角色范围十分重复
			Set<String> roleProgramEntry = new HashSet<String>();
			for(ProgramRolesVO row : batchItems.getCreateAndUpdateUnion()){
				if(roleProgramEntry.contains(row.getRoleId()+"|"+row.getProgramId())){
					getListInMap(errorInfo,"RoleProgramUniqueFail",String.class).add(row.getRoleName()+"+"+row.getProgramName());
				}else{
					roleProgramEntry.add(row.getRoleId()+"|"+row.getProgramId());
				}
			}
			//与数据库中已存在的数据校验角色范围是否重复
			List<String> errorNames = permissionDao.checkRoleProgramUnique(batchItems,userId);
			if(!errorNames.isEmpty()){
				getListInMap(errorInfo,"RoleProgramUniqueFail",String.class).addAll(errorNames);
			}
		}
		return errorInfo;
	}
	
	@SuppressWarnings("unchecked")
	private <T> Set<T> getListInMap(Map<String,Object> map, String type,Class<T> T){
		Set<T> set = (Set<T>)map.get(type);
		if(set == null){
			set = new HashSet<T>();
			map.put(type, set);
		}
		return set;
	}

	@Override
	public AuthorizationInfo findUserCurrentPermissions(Long userId) {
		// TODO Auto-generated method stub
		return null;
	}
}
